#!/usr/bin/env python
# vi: et sw=2
#
# Gnome PulseAudio applet - Preferences window
# Copyright (C) 2009  Harry Karvonen
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
#
# Author: Harry Karvonen <harry.karvonen@gmail.com>
#         Aki Rautio <aki.rautio@gmail.com>
#

import gobject
import sys

from xml_icons import StreamIcons
import pygtk
pygtk.require("2.0")

import gtk
import gtk.glade
from GnomePulseAppletInterface import PulseObj , \
                                      PulseSink, \
                                      PulseSinkInfo, \
                                      PulseSinkInputInfo, \
                                      PulseVolume
from conf import Config

## Global variables
APPLET_PATH = '/usr/share/gnome-pulse-applet'
GLADE_FILE = 'preferences.glade'

################################################################################
#
# PrefSinks

class Preferences:

  ##############################################################################
  #
  # Init
    def __init__(self,pulse_connection):
        

        ## Get configs
        self.config = Config()
        self.pulse = pulse_connection

        ## Set the Glade file
        self.gladefile = APPLET_PATH + '/' + GLADE_FILE
        self.glade = gtk.glade.XML( self.gladefile,"prefWindow")
        
        ## Create window variable for window opening and hiding.
        ## Make connection to disable window destroy when closing preferences
        self.window = self.glade.get_widget("prefWindow")        
        self.window.connect("destroy", self.close)
        self.window.connect("delete_event", self.close)
      
        self.selected_row = 0
        
        ## Create action dictionary and connect those with glade with
        actions = { 
        "on_prefWindow_hide"  : self.close,
        "on_change_layout"    : self.change_layout,
        "on_load_icons"       : self.load_icons,
        "on_save_icons"       : self.save_icons,
        "on_row_actived"      : self.change_active_row,
        "on_remove_icon_row"  : self.remove_icon_row,
        "on_use_xml"          : self.use_xml_file,
        "on_change_volumepos" : self.change_volume_pos
        }
        self.glade.signal_autoconnect(actions)
        
        
        
        ### Sinks Tab
        
        ## Sink object manages sinks
        self.sinkObject = PrefSinks(self.config,self.pulse)
        self.sinkObject.load()  
        self.sinkStore = self.sinkObject.get_store()

        self.sinksView = self.glade.get_widget("sinksView")
        self.AddSinksListColumn()
        

        self.sinksView.set_model(self.sinkStore)
        self.sinksView.set_reorderable(True)





        ### Stream Icons Tab

        ## Icon Object manages iconpaths
        self.iconObject = PrefIcons()
        self.iconObject.load()
        self.iconStore = self.iconObject.get_store()
        
        self.iconsView = self.glade.get_widget("iconsView")
        self.AddIconsListColumn()
        
        self.iconsView.set_model(self.iconStore)
        self.iconsView.set_reorderable(True)





        ## Make Checkbox and Radiobutton changed if needed
        
        ## Layout radio buttons
        self.radio_layout_vertical = self.glade.get_widget("radioVertical")
        self.radio_layout_horizontal = self.glade.get_widget("radioHorizontal")
        if self.config.get("layout") == "vertical":
          self.radio_layout_vertical.set_active(True)
        else:
          self.radio_layout_horizontal.set_active(True)

        ## Volume position
        self.check_volume_pos = self.glade.get_widget("checkVolumePos")
        if self.config.get_bool("show_vol_amount") == True:
          self.check_volume_pos.set_active(True)

        ## Stream icon checkbox
        ## TODO: Get PulseAudio version from object

        self.check_use_xml_file = self.glade.get_widget("checkPAicons")
        if self.config.get_bool("icon_use_xml") == True:
          self.check_use_xml_file.set_property("active",True)

        ## Distro name

        self.distroName = self.glade.get_widget("labelDistro")
        distroText = "You are using "
        self.distroName.set_label(distroText + self.config.get("distro"))




    ###
    ## Make Treeviews ( sinks and stream icons )ready for stores
    ###

    def AddSinksListColumn(self):			
        selectionRender = gtk.CellRendererToggle()
        selectionRender.set_property('activatable', True)
        selectionRender.set_radio(True)
        selectionRender.connect( 'toggled', self.change_sink, self.sinkStore )    
    
        textRender = gtk.CellRendererText()
    
        selectionColumn = gtk.TreeViewColumn("", selectionRender )
        selectionColumn.add_attribute( selectionRender, "active", 0)

        textColumn = gtk.TreeViewColumn("Sink Name", textRender, text=2)
    
        self.sinksView.append_column( selectionColumn )
        self.sinksView.append_column( textColumn )

    ###

    def AddIconsListColumn(self):			
        streamnameRender = gtk.CellRendererText()
        streamnameRender.set_property('editable', True)
        streamnameRender.connect('edited', self.change_icon_cell,1)
        streamnameColumn = gtk.TreeViewColumn("Stream name", streamnameRender, text=1)
        
        distroRender = gtk.CellRendererText()
        distroRender.set_property('editable', True)
        distroRender.connect('edited', self.change_icon_cell,2)
        distroColumn = gtk.TreeViewColumn("Distro", distroRender, text=2)
        
        iconpositionRender = gtk.CellRendererText()
        iconpositionRender.set_property('editable', True)
        iconpositionRender.connect('edited', self.change_icon_cell,3)        
        iconpositionColumn = gtk.TreeViewColumn("Icon location", iconpositionRender, text=3)   
        
        
        self.iconsView.append_column( streamnameColumn )
        self.iconsView.append_column( distroColumn )
        self.iconsView.append_column( iconpositionColumn )

    ###
    ## Action functions
    ###
    
    def change_layout(self ,event):       
        if event.get_active() == True:
            if event.get_name() == "radioVertical":
                self.config.save("layout", "vertical")
            elif event.get_name() == "radioHorizontal":
                self.config.save("layout", "horizontal")
        return 

    ###

    def change_sink(self, event, path, store):
      ### TODO: This doesn't work...maybe    
      if store[path][0] != True:
        for row in store:
           row[0] = False
        store[path][0] = True
        self.config.save("sink", store[path][1])
        self.selected_sink = self.pulse.pulse_sink_list()[store[path][1]]
      return

    ###

    def use_xml_file(self,event):
      if event.get_active():
        self.config.save_bool("icon_use_xml",True)
      else:
        self.config.save_bool("icon_use_xml",False)
      return

    ###

    def change_volume_pos(self,event):
      if event.get_active():
        self.config.save_bool("show_vol_amount",True)
      else:
        self.config.save_bool("show_vol_amount",False)
      return

    ###

    def load_icons(self,event):
      self.iconObject.load()   
      self.iconsView.set_model(self.iconObject.get_store())
      return

    ###
    def change_icon_cell(self, cell_render, row, text,column):
      self.iconObject.change_value(column,row,text)
      return
    
    ###

    def change_active_row(self,treeview):
      position = treeview.get_cursor()[0]
      self.selected_row = position[0]
      return

    ###    
    def remove_icon_row(self, event):
      if len(self.iconObject.get_store() ) != self.selected_row+1:
        self.iconObject.remove_row(self.selected_row)
      
      return

    ###

    def save_icons(self,event):
      self.iconObject.save()
      return

    ###
    ## Functions for closing and opening preferences window
    ###
    
    def close(self,event,data = ""):
      self.window.hide()
      return True

    ###

    def open_window(self):
      self.window.show_all()
      return True

################################################################################
#
# PrefSinks

class PrefSinks:

  ##############################################################################
  #
  # Init
  def __init__(self,config,pulse):
    self.sinkStore = gtk.ListStore( gobject.TYPE_BOOLEAN ,
                                  gobject.TYPE_INT ,
                                  gobject.TYPE_STRING )
    
    self.config = config # Get configs        
    self.pulse = pulse

    # Check if PulseAudio is connected 
    if self.pulse.connected:
      self.selected_sink = self.pulse.pulse_sink_list()[int(
                                                      self.config.get("sink"))]
    else:
      self.selected_sink = None
    
    # Check if the sink exists
    if int(self.config.get("sink")) >= len(self.pulse.pulse_sink_list()):
      self.config.save("sink", 0)

  ###

  def load(self):
    sink_number = 0
    for sink_name in self.pulse.pulse_sink_list():
      if sink_name.index == self.selected_sink.index:
        radio_active = True
      else:
        radio_active = False
      
      self.sinkStore.append( (radio_active,sink_number,
                        str(sink_name.name)) )
    return

  ###

  def get_store(self):
    return self.sinkStore 

################################################################################
#
# PrefIcons

class PrefIcons:

  ##############################################################################
  #
  # Init
  def __init__(self):
    self.icons = StreamIcons()    
    self.size = 0
    self.store = gtk.ListStore( gobject.TYPE_INT ,
                                  gobject.TYPE_STRING ,
                                  gobject.TYPE_STRING ,
                                  gobject.TYPE_STRING )
    
     
  ###

  def load(self):
    self.store.clear()    
    self.icons.loadStreamIcons()      
    for sink_icon in self.icons.listAllStreamIcons():
      self.store.append(  (self.size,
                          str(sink_icon.getName()),
                          str(sink_icon.getDistro()),
                          str(sink_icon.getPath()) ) )
      self.size = self.size + 1   
    self.store.append( (self.size, "","","") )    
    return

  ###

  def change_value(self,column,row,text):
    if int(self.size) == int(row):
      self.add_row(column,text)
    else:
      self.store[row][column] = text
      self.icons.setStreamIcon(int(row),int(column),text)
    return

  ###
  
  def add_row(self,column,text):
    stream = ""
    distro = ""    
    path = ""
    if column == 1:
      stream == text
    elif column == 2:
      distro == text
    else:
      path == text
    self.store.append( (self.size,stream,distro,path))
    self.icons.setStreamIcon(int(self.size),int(column),text)    
    self.size = self.size + 1
    return

  ###

  def remove_row(self,row):   
    self.store.remove(self.store[row].iter)
    self.icons.removeStreamIcon(row)
    return

  ###

  def save(self):
    self.icons.saveToXML()
    return

  ###

  def get_store(self):

    return self.store


#####################################################################


##if __name__ == "__main__":
##	preferences = Preferences()
##	gtk.main()
